﻿// An example script that demonstrates Response Fingerprinting
// The script creates a network, matures it in the presence of background stimulation (only), and the mature network is then profiled and fingerprinted
// The mature network is then trained on an 'Ascending' firing pattern, and the trained network is re-profiled and re-fingerprinted
// With these setting, even an untrained network can produce consistent temporal windows, although the number from a trained network is much higher
// However, the final fingerprint is normally filtered with a more aggressive threshold for further use
// Maturation takes a long time, training and profiling take an intermediate time, and fingerprinting is very fast

#r @"C:\Users\Mira\Source\Repos\Spinula\Debug\SpikingNeuronLib.dll"
#r @"C:\Users\Mira\Source\Repos\Spinula\SpikingAnalyticsBaseLib\bin\Debug\SpikingAnalyticsBaseLib.dll"
#r @"C:\Users\Mira\Source\Repos\Spinula\SpikingAnalyticsLib\bin\Debug\SpikingAnalyticsLib.dll"

open System
open System.IO
open SpikingNeuronLib
open SpikingAnalyticsLib
open SpikingAnalyticsLib.ResponseFingerPrint
open SpikingAnalyticsLib.PatternExtensions

let outputFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
let backgroundFiringRate = 1            // one hertz background for maturation, training and profiling
let patternName = "Ascending"           // pattern used for training and profiling
let includeInhibitoryNeurons = false    // inhibitory neurons included for fingerprinting
let runSeconds = 2 * 3600               // two hour maturation period
let patternStimulationsPerSecond = 5    // training frequency
let trainSeconds = 120                  // training period
let verbose = true                      // profiling feedback

let matureNetworkBaseName = "MatureNetwork"
let trainedNetworkBaseName = "TrainedNetwork"
let profileNameMatureNetwork = sprintf "profile_%s.txt" matureNetworkBaseName
let profileNameTrainedNetwork = sprintf "profile_%s.txt" trainedNetworkBaseName

// Create a linear firing pattern composed of 40 firing events, one each millisecond
let pattern = Pattern.FromLinearSequence(1, 1, 40)
let stimulus = Stimulus.Create(patternStimulationsPerSecond, pattern)

// Create a mature network composed of 1000 randomly connected neurons
CrossbarNetwork.CreateMatureNetwork(runSeconds, backgroundFiringRate, CrossbarNetworkSpecifier.N1000Network, outputFolder, matureNetworkBaseName)

// load the matured network
let matureNetwork = CrossbarNetwork.CreateFromFile(Path.Combine(outputFolder, sprintf "%s%d.txt" matureNetworkBaseName runSeconds))

// Profile the network's response to the stimulus
let profileBefore = new FrameProfile(matureNetwork, Some(pattern), patternName, backgroundFiringRate, verbose)

// Save the profile
profileBefore.Save(Path.Combine(outputFolder, profileNameMatureNetwork))

// Create a response fingerprint (temporal windows)
let windowMapBeforeTraining = new WindowMap(profileBefore, includeInhibitoryNeurons, verbose)

// Train the network on a 5 Hz stimulus for 120 secs
matureNetwork.Train(stimulus, trainSeconds, backgroundFiringRate, outputFolder, trainedNetworkBaseName)

// load the trained network
let trainedNetwork = CrossbarNetwork.CreateFromFile(Path.Combine(outputFolder, sprintf "%s%d.txt" trainedNetworkBaseName trainSeconds))

// Re-profile the network's response to the stimulus
let profileAfter = new FrameProfile(trainedNetwork, Some(pattern), patternName, backgroundFiringRate, verbose)

// Save the profile
profileAfter.Save(Path.Combine(outputFolder, profileNameTrainedNetwork))

// Create the post-training response fingerprint
let windowMapAfterTraining = new WindowMap(profileAfter, includeInhibitoryNeurons, verbose)

printfn "%d %d" (windowMapBeforeTraining.AllWindows.Count) (windowMapAfterTraining.AllWindows.Count)
